print("in test_lua_register.lua")

local pos = nil
local pos2 = nil

local cat = nil
local dog = nil
local husky = nil

-- 垃圾收集
function collect_garbage()
	local garbage_count = collectgarbage("count")
	print("before gc: garbage_count = "..garbage_count)
	
	collectgarbage("collect")
	
	garbage_count = collectgarbage("count")
	print("after gc: garbage_count = "..garbage_count)
end

-- 测试构造函数，即在lua中构造对象
function test_constructor()
	print("\n-------------------- test_constructor --------------------")
	
	pos = Position.new()
	print("pos = ("..pos.x..","..pos.y..")")

	pos2 = Position.new2(2,3)
	print("pos2 = ("..pos2.x..","..pos2.y..")")
	
	husky = test.Husky()
	print("husky = "..tostring(husky))
	
	dog = test.Dog.new("my dog")
	print("dog = "..tostring(dog))
	
	cat = test.Cat.new("kitty")
	print("cat = "..tostring(cat))
	
end

-- 在lua中构造的对象可以在lua中析构
-- 可以显式调用析构函数，或者设置为nil，通过垃圾清理销毁
function test_destruction()
	print("\n-------------------- test_destruction --------------------")

	--dog = nil
	--husky = nil
	
	cat = nil
	
	
	local mimi = test.Cat("mimi")
	
	collect_garbage()
end

-- 测试导出函数
function test_function()
	print("\n-------------------- test_function --------------------")

	print("---------global function----------")
	
	g_intro_animal(dog)
	
	local cat_name = g_get_animal_name(cat)
	print("cat_name = "..cat_name)

	print("---------class method----------")
	
	dog:bark()
	
	husky:bark()
	
	dog:bite(husky)
	
	cat:scratch(dog)
end

-- 测试成员变量导出
function test_member()
	print("\n-------------------- test_member --------------------")
	print("--------readwrite---------")
	print("pos2 = ("..pos2.x..","..pos2.y..")")
	print("set pos2 = (77,88)")
	pos2.x = 77
	pos2.y = 88
	print("pos2 = ("..pos2.x..","..pos2.y..")")
	
	print("--------readonly---------")
	print("pos2.len = "..pos2.len)
	print("set pos2.len = 10000")
	--pos2.len = 10000
	print("pos2.len = "..pos2.len)
	
end

-- 测试类的导出属性(getter, setter)
function test_property()
	print("\n-------------------- test_property --------------------")

	print("------readwrite-------")
	print("dog.name = "..dog.name)
	dog.name = "da huang"
	print("set dog.name to 'da huang'")
	print("dog_name = "..dog.name)
	
	print("------readonly-------")
	print("dog.color = "..dog.color)
	--dog.color = "red" -- error
	--print("set dog.color to 'red'")
	--print("dog.color = "..dog.color)
end

-- 测试变量的导出
function test_variant()
	print("\n-------------------- test_variant --------------------")
	
	print("------global variant-------")
	
	print("g_pos_rw = ("..test.g_pos_rw.x..","..test.g_pos_rw.y..")")
	--test.g_pos_rw.x = 8765
	test.g_pos_rw = pos
	print("set g_pos_rw.x to (0,0)")
	print("g_pos_rw = ("..test.g_pos_rw.x..","..test.g_pos_rw.y..")")
	
	print("---------------")
	print("g_pos_r = ("..test.g_pos_r.x..","..test.g_pos_r.y..")")
	--test.g_pos_r.x = 5678 -- g_pos_r 是只读的不能赋值，但是其成员变量却可以被赋值，这是个bug
	test.g_pos_r = pos
	print("set g_pos_r.x to (0,0)")
	print("g_pos_r = ("..test.g_pos_r.x..","..test.g_pos_r.y..")")

	print("---------------")
	print("g_pos_v = ("..test.g_pos_v.x..","..test.g_pos_v.y..")")
	--test.g_pos_v.x = 5555
	test.g_pos_v = pos
	print("set g_pos_v.x to (0,0)")
	print("g_pos_v = ("..test.g_pos_v.x..","..test.g_pos_v.y..")")
	
	print("------class member-------")
	print("pos.x = "..pos.x)
	print("pos.y = "..pos.y)
end


-- 测试导出的STL类型
function test_stl()
	print("\n-------------------- test_stl --------------------")
	
	print("-----------vector/list-----------")
	local dog_list = husky.friends
	for i=0, dog_list.size-1 do
		local dog = dog_list:at(i)
		dog:bark()
	end
	
	print("-----------------map-----------------")
	local print_map = function(map)
		local it = map.head	
		while not it:equal(map.tail) do
			print(it.key.." = "..it.value)
			
			it:increase()
		end	
	end
	
	local schoolmates = husky.school_mates
	local it = schoolmates.head
	while not it:equal(schoolmates.tail) do
		local dog = it.value
		print(it.key.." = "..dog.name)
		it:increase()
	end
	
	print("---------------------")
	local others = husky.others
	local it = others.head
	while not it:equal(others.tail) do
		print("  "..it.key)
		local dogs = it.value
		for i=0,dogs.size-1 do
			local d = dogs:at(i)
			print("    "..d.name)
		end
		it:increase()
	end
	
	print("---------------------")
	
	local dog_map = husky.friend_infos
	print_map(dog_map)
	
	dog_map:clear()
	print("dog_map:clear(), dog_map.is_empty = "..tostring(dog_map.is_empty))
	
	dog_map:insert("lili", "Pakistan")
	dog_map:insert("amanda", "india")
	dog_map:insert("tulu", "mongolia")
	dog_map:insert("KimJinKu", "Korea")
	dog_map:insert("Gutuli", "Vietnam")
	print_map(dog_map)

end

-- 测试临时对象
--[[
	如果函数返回值是一个临时对象的话，可能传到lua后，该对象已经被销毁
	所以要在C++中new一个新对象来保存这个对象
	这个对象会在lua中gc的时候被清理
]]
function test_temp_object()
	print("\n-------------------- test_temp_object --------------------")
	-- husky.girlfriend 调用的C++函数会产生一个临时对象，
	-- 这个临时对象被复制一份传递给lua，然后就被析构了，
	-- 所以这里会产生一次额外的拷贝构造和析构
	-- 而新产生的对象作为husky的一部分，只有husky被析构的时候才销毁
	local girl_cat = husky.girlfriend
	girl_cat:bark()
	
	girl_cat = nil
	collect_garbage()
	-- 注意gril_cat是一个引用，引向了husky.girlfriend
	-- 所以这时候gril_cat=nil不会导致Cat对象的析构
	-- 只有当husky被gc的时候，Cat对象才会被析构
	
	-- 虽然多产生了一次构造析构，但是对象最后还是会被销毁的，没毛病
end

-- 测试C++中导出的lua表（将C++中的map和vector导出成lua中的表）
function test_simple_table()
	print("\n-------------------- test_simple_table --------------------")

	local print_table = function(t)
		for k, v in pairs(t) do
			print(tostring(k).." = "..tostring(v.name))
		end
	end

	print("-------- my_dog_array ----------")
	print_table(my_dog_array)
	
	print("-------- my_dog_band ----------")
	print_table(my_dog_band)

end


function test_object_counter()
	print("------ ObjectCounter.count = "..ObjectCounter.count())
	
	local dogs = {}
	for i=1, 10 do
		local d = test.Dog("wolf")
		table.insert(dogs, d)
	end
	
	print("------ ObjectCounter.count = "..ObjectCounter.count())
	
	dogs = nil
	collect_garbage()
	
	print("------ ObjectCounter.count = "..ObjectCounter.count())

end


function main()
--[[
	test_constructor()
	
	test_function()
	
	test_property()
	
	test_member()
	
	test_variant()
	
	test_stl()
	
	test_temp_object()
	
	test_simple_table()
	
	test_destruction()
--]]

	test_object_counter()

	print("================== test finish ==================")
end




-- run...
main()































